Startup
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
── Attaching packages ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.6 ✔ purrr 0.3.4
✔ tibble 3.1.4 ✔ dplyr 1.0.7
✔ tidyr 1.1.3 ✔ stringr 1.4.0
✔ readr 2.0.1 ✔ forcats 0.5.1
── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
library(cowplot)
library(ggpmisc)
Loading required package: ggpp
Attaching package: ‘ggpp’
The following object is masked from ‘package:ggplot2’:
annotate
library(here)
here() starts at /labs/khatrilab/solomonb/hla_project/hla_benchmark
source(here("helper_functions/data_import_functions.R"))
source(here("helper_functions/figure_format_functions.R"))
Loading required package: flextable
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Registered S3 methods overwritten by 'htmltools':
method from
print.html tools:rstudio
print.shiny.tag tools:rstudio
print.shiny.tag.list tools:rstudio
Attaching package: ‘flextable’
The following object is masked from ‘package:purrr’:
compose
source(here("helper_functions/calculation_functions.R"))
Loading required package: tidymodels
Registered S3 method overwritten by 'tune':
method from
required_pkgs.model_spec parsnip
── Attaching packages ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidymodels 0.1.3 ──
✔ broom 0.7.9 ✔ rsample 0.1.0
✔ dials 0.0.9 ✔ tune 0.1.6
✔ infer 1.0.0 ✔ workflows 0.2.3
✔ modeldata 0.1.1 ✔ workflowsets 0.1.0
✔ parsnip 0.1.7 ✔ yardstick 0.0.8
✔ recipes 0.1.16
── Conflicts ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidymodels_conflicts() ──
✖ ggpp::annotate() masks ggplot2::annotate()
✖ flextable::compose() masks purrr::compose()
✖ scales::discard() masks purrr::discard()
✖ dplyr::filter() masks stats::filter()
✖ recipes::fixed() masks stringr::fixed()
✖ dplyr::lag() masks stats::lag()
✖ yardstick::spec() masks readr::spec()
✖ recipes::step() masks stats::step()
• Use tidymodels_prefer() to resolve common conflicts.
Loading required package: checkmate
Attaching package: ‘checkmate’
The following object is masked from ‘package:recipes’:
check_class
Loading required package: lubridate
Attaching package: ‘lubridate’
The following object is masked from ‘package:cowplot’:
stamp
The following objects are masked from ‘package:base’:
date, intersect, setdiff, union
isb_path <- here("data/isb")
isb_samples <- read_tsv(here("data/isb/logs/parallel.log")) %>%
separate(Command, into = c(NA, "sample"), sep = " ") %>%
pull(sample) %>% unique()
Rows: 294 Columns: 9
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (2): Host, Command
dbl (7): Seq, Starttime, JobRuntime, Send, Receive, Exitval, Signal
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Get reference alleles
reference_alleles <- read_tsv(here("references/GCh38_reference_alleles.txt"), col_names = F) %>% pull(1)
Rows: 26 Columns: 1
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (1): X1
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
genome_region_reference <- get_allele_length(reference_alleles)
Get arcasHLA alignment stats
arcas_log_dir <- sprintf("%s/arcasHLA", isb_path)
alignment_stats_df <- hla_mapping_stats_import(isb_samples, arcas_log_dir)
Import cell counts
cell_counts_df <- readRDS(here("data/isb/isb_sequenced_cell_count.RDS"))
Assemble accuracy DF
success_df <- readRDS(here("2_accuracy/isb_success.RDS"))
accuracy_df <- readRDS(here("3_DRB/isb_accuracy_drb345_filtered.RDS"))
accuracy_df <- accuracy_df %>%
left_join(
success_df %>% select(sample:field, genotyper, success = accuracy),
by = c("sample", "locus", "field", "genotyper")
)%>%
left_join(alignment_stats_df, by = c("sample", "locus")) %>%
left_join(genome_region_reference, by = "locus") %>%
left_join(cell_counts_df, by = "sample") %>%
mutate_at(vars(c(reads, bp)), as.numeric) %>%
mutate(coverage = (reads * 91)/bp) %>%
mutate(n_alleles = map_dbl(allele, function(x) sum(!is.na(x)))) %>%
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)$", sample) & genotyper != "hlaminer")
Coverage based plots
gg_coverage(accuracy_df, x_var = "coverage", y_var = "accuracy")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(accuracy_df, x_var = "coverage", y_var = "success")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(accuracy_df, x_var = "coverage", y_var = "n_alleles", facet_genotyper = T)

Cell number based plots
gg_coverage(accuracy_df, x_var = "n_cells", y_var = "accuracy")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(accuracy_df, x_var = "n_cells", y_var = "success")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(accuracy_df, x_var = "n_cells", y_var = "n_alleles", facet_genotyper = T)

Subsample READS
Import read subsample data
# Import predicted genotypes
subsample_reads_path <- here("data/isb/subsample")
subsample_reads_samples <- tibble(sample = list.files(sprintf("%s/arcasHLA", subsample_reads_path))) %>%
filter(grepl("^INCOV", sample)) %>%
separate(sample, into = c("sample"), sep = "\\.", extra = "drop") %>%
distinct() %>%
pull(sample)
subsample_reads_df <- format_hla_table(combine_HLA_import(path = subsample_reads_path, samples = subsample_reads_samples))
subsample_reads_df <- subsample_reads_df %>%
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)_", sample))
subsample_reads_df
# Expand invitro genotypes across read subsample names
invitro_df <- invitro_import()
Rows: 1557 Columns: 9
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (8): Sample ID, Locus, Allele 1, Allele 2, Comments, Diploid Ambiguities, Allele 1 Ambiguities, Allele 2 Ambiguities
dbl (1): index
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
invitro_reads_df <- subsample_reads_df %>%
select(sample) %>%
distinct() %>%
separate(sample, into = c("sample", "subsample"), sep = "_") %>%
left_join(invitro_df, by = "sample") %>%
unite(sample, sample, subsample, sep = "_") %>%
format_hla_table() %>%
drop_na()
invitro_reads_df
# Import read statistics
subsample_reads_arcas_log_dir <- sprintf("%s/arcasHLA", subsample_reads_path)
subsample_reads_alignment_stats_df <- hla_mapping_stats_import(subsample_reads_samples, subsample_reads_arcas_log_dir)
Calculate accuracy
# Calculate accuracy
subsample_reads_accuracy_df <- compare_hla(
hla_df = bind_rows(
subsample_reads_df,
invitro_reads_df
),
reference = "invitro",
method = "accuracy"
)
# saveRDS(subsample_reads_accuracy_df, "isb_subsample_reads_accuracy.RDS")
# Calculate success
subsample_reads_success_df <- compare_hla(
hla_df = bind_rows(
subsample_reads_df,
invitro_reads_df
),
reference = "invitro",
method = "success"
)
# saveRDS(subsample_reads_success_df, "isb_subsample_reads_success.RDS")
# Combine various data
subsample_reads_combined_df <- subsample_reads_accuracy_df %>%
left_join(
subsample_reads_success_df %>% select(sample:field, genotyper, success = accuracy),
by = c("sample", "locus", "field", "genotyper")
)%>%
left_join(subsample_reads_alignment_stats_df, by = c("sample", "locus")) %>%
left_join(genome_region_reference, by = "locus") %>%
bind_rows(accuracy_df %>% select(-n_cells)) %>% # No cell numbers for read subsamples
mutate_at(vars(c(reads, bp)), as.numeric) %>%
mutate(coverage = (reads * 91)/bp) %>% # Calculate coverage
mutate(n_alleles = map_dbl(allele, function(x) sum(!is.na(x)))) %>% # Calculate n_alleles
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)", sample) & genotyper != "hlaminer")
# saveRDS(subsample_reads_combined_df, "subsample_reads_combined_df.RDS")
# subsample_reads_combined_df <- readRDS("subsample_reads_combined_df.RDS")
Reads plots
gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "accuracy")
`geom_smooth()` using formula 'y ~ x'

plt_read_accuracy_all <- gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "accuracy")
plt_read_accuracy_abc <- gg_coverage(subsample_reads_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "reads", y_var = "accuracy")
gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "success")
`geom_smooth()` using formula 'y ~ x'

plt_read_success_all <- gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "success")
plt_read_success_abc <- gg_coverage(subsample_reads_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "reads", y_var = "success")
gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "n_alleles", facet_genotyper = T)

plt_read_allele_all <- gg_coverage(subsample_reads_combined_df, x_var = "reads", y_var = "n_alleles", facet_genotyper = T)
plt_read_allele_abc <- gg_coverage(subsample_reads_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "reads", y_var = "n_alleles", facet_genotyper = T)
- Default arcasHLA cut off 75 reads (log10 = 1.8)
subsample_reads_combined_df %>%
filter(field == "field_2") %>%
mutate(n_alleles = factor(n_alleles, levels = 0:2)) %>%
ggplot(aes(y = n_alleles, x = log10(coverage)))+
# geom_violin(scale = "count", alpha = 0.5, )+
geom_jitter(size = 0.2, width = 0, height =0.2, alpha = 0.2)+
# geom_boxplot(width=0.1)+
# ggbeeswarm::geom_beeswarm(size = 0.1, alpha = 0.1)+
# coord_flip()+
facet_grid(genotyper ~ locus, scales = "free")+
theme_bw()

Subsample CELLS
# Import predicted genotypes
subsample_cells_path <- here("data/isb/subsample_cells")
subsample_cells_samples <- tibble(sample = list.files(sprintf("%s/arcasHLA", subsample_cells_path))) %>%
filter(grepl("^INCOV", sample)) %>%
separate(sample, into = c("sample"), sep = "\\.", extra = "drop") %>%
distinct() %>%
pull(sample)
subsample_cells_df <- format_hla_table(combine_HLA_import(path = subsample_cells_path, samples = subsample_cells_samples))
subsample_cells_df <- subsample_cells_df %>%
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)_", sample))
subsample_cells_df
# Expand invitro genotypes across read subsample names
invitro_df <- invitro_import()
Rows: 1557 Columns: 9
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (8): Sample ID, Locus, Allele 1, Allele 2, Comments, Diploid Ambiguities, Allele 1 Ambiguities, Allele 2 Ambiguities
dbl (1): index
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
invitro_cells_df <- subsample_cells_df %>%
select(sample) %>%
distinct() %>%
separate(sample, into = c("sample", "subsample"), sep = "_") %>%
left_join(invitro_df, by = "sample") %>%
unite(sample, sample, subsample, sep = "_") %>%
format_hla_table() %>%
drop_na()
invitro_cells_df
# Import read statistics
subsample_cells_arcas_log_dir <- sprintf("%s/arcasHLA", subsample_cells_path)
subsample_cells_alignment_stats_df <- hla_mapping_stats_import(subsample_cells_samples, subsample_cells_arcas_log_dir)
# Import cell counts for each subsample
subsample_cell_counts_df <- read_csv(here("data/isb/subsample_cells/subsample_cell_counts.csv"))
Rows: 1176 Columns: 2
── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): sample
dbl (1): n_cells
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Calculate accuracy
# Calculate accuracy
subsample_cells_accuracy_df <- compare_hla(
hla_df = bind_rows(
subsample_cells_df,
invitro_cells_df
),
reference = "invitro",
method = "accuracy"
)
# saveRDS(subsample_cells_accuracy_df, "isb_subsample_cells_accuracy.RDS")
# subsample_cells_accuracy_df <- readRDS("isb_subsample_cells_accuracy.RDS")
# Calculate success
subsample_cells_success_df <- compare_hla(
hla_df = bind_rows(
subsample_cells_df,
invitro_cells_df
),
reference = "invitro",
method = "success"
)
# saveRDS(subsample_cells_success_df, "isb_subsample_cells_success.RDS")
# subsample_cells_success_df <- readRDS("isb_subsample_cells_success.RDS")
# Combine various data
subsample_cells_combined_df <- subsample_cells_accuracy_df %>%
left_join(
subsample_cells_success_df %>% select(sample:field, genotyper, success = accuracy),
by = c("sample", "locus", "field", "genotyper")
)%>%
left_join(subsample_cells_alignment_stats_df, by = c("sample", "locus")) %>%
left_join(genome_region_reference, by = "locus") %>%
left_join(subsample_cell_counts_df, by = "sample") %>%
bind_rows(accuracy_df) %>%
mutate_at(vars(c(reads, bp)), as.numeric) %>%
mutate(coverage = (reads * 91)/bp) %>%
mutate(n_alleles = map_dbl(allele, function(x) sum(!is.na(x)))) %>%
filter(grepl("^[ABC]|D.[AB]1", locus) & grepl("-(AC|BL)", sample) & genotyper != "hlaminer")
# saveRDS(subsample_cells_combined_df, "subsample_cells_combined_df.RDS")
Coverage plots
gg_coverage(subsample_cells_combined_df, x_var = "coverage", y_var = "accuracy")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(subsample_cells_combined_df, x_var = "coverage", y_var = "success")
`geom_smooth()` using formula 'y ~ x'

gg_coverage(subsample_cells_combined_df, x_var = "coverage", y_var = "n_alleles", facet_genotyper = T)

Cell number plots
gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "accuracy")
`geom_smooth()` using formula 'y ~ x'

plt_cell_accuracy_all <- gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "accuracy")
plt_cell_accuracy_abc <- gg_coverage(subsample_cells_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "n_cells", y_var = "accuracy")
gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "success")
`geom_smooth()` using formula 'y ~ x'

plt_cell_success_all <- gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "success")
plt_cell_success_abc <- gg_coverage(subsample_cells_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "n_cells", y_var = "success")
gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "n_alleles", facet_genotyper = T)

plt_cell_allele_all <- gg_coverage(subsample_cells_combined_df, x_var = "n_cells", y_var = "n_alleles", facet_genotyper = T)
plt_cell_allele_abc <- gg_coverage(subsample_cells_combined_df %>% filter(grepl("^[ABC]", locus)), x_var = "n_cells", y_var = "n_alleles", facet_genotyper = T)
# subsample_cells_combined_df %>%
# mutate(reads = reads/n_cells) %>%
# filter(reads < 100) %>%
# gg_coverage(x_var = "reads", y_var = "accuracy", x_log = F)
Combined plots
no_leg <- list(theme(legend.position = "none"))
legend <- cowplot::get_legend(plt_read_accuracy_abc)
`geom_smooth()` using formula 'y ~ x'
plot_grid(
plot_grid(
plt_read_accuracy_abc + no_leg,
plt_read_success_abc + no_leg,
plt_read_allele_abc,
ncol = 1,
align = "v",
axis = "lr",
rel_heights = c(1,1,1.2),
labels = LETTERS[1:3]
),
plot_grid(
plt_cell_accuracy_abc + no_leg,
plt_cell_success_abc + no_leg,
plt_cell_allele_abc,
ncol = 1,
align = "v",
axis = "lr",
rel_heights = c(1,1,1.2),
labels = LETTERS[4:6]
),
plot_grid(
legend,
legend,
NA,
ncol = 1
),
nrow = 1,
rel_widths = c(1,1,0.25)
)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'

no_leg <- list(theme(legend.position = "none"))
legend <- cowplot::get_legend(plt_read_accuracy_all)
`geom_smooth()` using formula 'y ~ x'
plot_grid(
plot_grid(
plt_read_accuracy_all + no_leg,
plt_read_success_all + no_leg,
plt_read_allele_all,
ncol = 1,
align = "v",
axis = "lr",
rel_heights = c(1,1,1.2),
labels = LETTERS[1:3]
),
plot_grid(
plt_cell_accuracy_all + no_leg,
plt_cell_success_all + no_leg,
plt_cell_allele_all,
ncol = 1,
align = "v",
axis = "lr",
rel_heights = c(1,1,1.2),
labels = LETTERS[4:6]
),
plot_grid(
legend,
legend,
NA,
ncol = 1
),
nrow = 1,
rel_widths = c(1,1,0.25)
)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'

Main plot
loci <- c("A", "B", "C", "DPB1", "DQA1", "DRB1")
plt_read_accuracy_subset <- gg_coverage(
subsample_reads_combined_df %>%
filter(locus %in% loci) %>%
filter(!(genotyper == "phlat" & locus == "DPB1")) %>%
filter(!(genotyper == "optitype" & locus == "DPB1")) %>%
filter(!(genotyper == "optitype" & locus == "DQA1")) %>%
filter(!(genotyper == "optitype" & locus == "DRB1")),
x_var = "reads", y_var = "accuracy") +
facet_wrap(~locus, nrow = 2)
plt_read_accuracy_subset
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 59 rows containing non-finite values (stat_smooth).
Warning: Removed 59 rows containing missing values (geom_point).

save_plot(here("figures_pdf/v2/5_coverage.pdf"), plt_read_accuracy_subset, base_height = 4, base_width = 6)
plt_read_allele_all <- gg_coverage(subsample_reads_combined_df %>%
filter(locus %in% loci) %>%
filter(!(genotyper == "phlat" & locus == "DPB1")) %>%
filter(!(genotyper == "optitype" & locus == "DPB1")) %>%
filter(!(genotyper == "optitype" & locus == "DQA1")) %>%
filter(!(genotyper == "optitype" & locus == "DRB1")), x_var = "reads", y_var = "n_alleles", facet_genotyper = T)
plt_read_allele_all
Warning: Removed 62 rows containing missing values (geom_point).

plt_main <- plot_grid(
plt_read_accuracy_subset,
plt_read_allele_all,
ncol = 1,
rel_heights = c(3,2),
align = "v",
axis = "lr",
labels = c("A", "B")
)
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 59 rows containing non-finite values (stat_smooth).
Warning: Removed 59 rows containing missing values (geom_point).
Warning: Removed 62 rows containing missing values (geom_point).
plt_main

save_plot(here("figures_pdf/v2/5_coverage.pdf"), plt_main, base_height = 7, base_width = 7)
Slope stats
get_lm_stats <- function(df, x_var = "coverage", y_var = "accuracy", field_var = "field_2", x_log = T){
# Input checks
arg_col <- makeAssertCollection()
assertChoice(y_var, c("accuracy", "success", "n_alleles"), add = arg_col)
assertChoice(x_var, c("reads", "coverage", "n_cells"), add = arg_col)
assertChoice(field_var, c("field_1", "field_2", "field_3"), add = arg_col)
assertLogical(x_log, add = arg_col)
if (arg_col$isEmpty()==F) {map(arg_col$getMessages(),print);reportAssertions(arg_col)}
# browser()
df <- df %>%
filter(field == field_var) %>%
exclude_genotyper_fields() # Replace w/ exclude_genotyper_fields?
if (x_log ==T){df <- df %>% mutate_at(x_var, log10)}
df %>%
filter_at(x_var, function(x) !is.na(x) & !is.infinite(x)) %>%
group_by(locus, field, genotyper) %>%
nest() %>%
mutate(data = map(data, function(x){
summary(lm(!!sym(y_var) ~ !!sym(x_var), data = x)) %>% broom::tidy() %>% filter(term == x_var)
})) %>% unnest_wider(data) %>%
mutate(est_min = round(estimate - 2*std.error, 2),
est_max = round(estimate + 2*std.error, 2))
}
model_stats <- get_lm_stats(subsample_cells_combined_df, x_var = "reads", y_var = "accuracy", x_log = T)
model_stats
model_stats <- bind_rows(
get_lm_stats(subsample_reads_combined_df, x_var = "reads", y_var = "accuracy", x_log = T) %>% mutate(x_var = "reads", y_var = "accuracy"),
get_lm_stats(subsample_reads_combined_df, x_var = "reads", y_var = "success", x_log = T) %>% mutate(x_var = "reads", y_var = "success"),
get_lm_stats(subsample_cells_combined_df, x_var = "n_cells", y_var = "accuracy", x_log = T) %>% mutate(x_var = "cells", y_var = "accuracy"),
get_lm_stats(subsample_cells_combined_df, x_var = "n_cells", y_var = "success", x_log = T) %>% mutate(x_var = "cells", y_var = "success")
) %>%
# filter(grepl("^[ABC]", locus)) %>%
ungroup() %>%
filter(field == "field_2")
Table
| Reads | Cells |
| A | B | C | DPA1 | DPB1 | DQA1 | DQB1 | DRB1 | A | B | C | DPA1 | DPB1 | DQA1 | DQB1 | DRB1 |
Accuracy | arcasHLA | (0.09) - (0.14) | (0.09) - (0.14) | (0.11) - (0.15) | (0.26) - (0.29) | (0.23) - (0.28) | (0.26) - (0.3) | (0.23) - (0.27) | (0.19) - (0.24) | (0.04) - (0.1) | (0.05) - (0.11) | (0.06) - (0.11) | (0.29) - (0.34) | (0.26) - (0.32) | (0.3) - (0.35) | (0.26) - (0.31) | (0.18) - (0.24) |
OptiType | (-0.05) - (0) | (-0.03) - (0.02) | (-0.01) - (0.03) | --- | --- | --- | --- | --- | (-0.06) - (0) | (-0.04) - (0.01) | (-0.04) - (0.02) | --- | --- | --- | --- | --- |
PHLAT | (0.05) - (0.1) | (0.07) - (0.12) | (0.08) - (0.12) | --- | --- | (0.18) - (0.22) | (0.18) - (0.22) | (0.13) - (0.18) | (0.04) - (0.09) | (0.06) - (0.11) | (0.05) - (0.1) | --- | --- | (0.23) - (0.28) | (0.21) - (0.26) | (0.15) - (0.2) |
Success | arcasHLA | (-0.07) - (0.01) | (-0.01) - (0.07) | (-0.01) - (0.07) | (0.04) - (0.11) | (-0.01) - (0.09) | (-0.04) - (0.06) | (-0.04) - (0.08) | (-0.04) - (0.03) | (-0.01) - (0.06) | (0.01) - (0.09) | (-0.01) - (0.06) | (0.1) - (0.17) | (0.04) - (0.14) | (0.04) - (0.14) | (0.01) - (0.12) | (-0.02) - (0.05) |
OptiType | (0.01) - (0.06) | (0.03) - (0.08) | (0.05) - (0.09) | --- | --- | --- | --- | --- | (0.01) - (0.07) | (0.02) - (0.08) | (0.03) - (0.08) | --- | --- | --- | --- | --- |
PHLAT | (0.05) - (0.1) | (0.08) - (0.13) | (0.08) - (0.12) | --- | --- | (0.12) - (0.18) | (0.11) - (0.17) | (0.12) - (0.17) | (0.04) - (0.1) | (0.06) - (0.13) | (0.05) - (0.11) | --- | --- | (0.13) - (0.21) | (0.12) - (0.18) | (0.12) - (0.18) |
Scratch work
LS0tCnRpdGxlOiAiNSkgQ292ZXJhZ2UgQW5hbHlzaXMiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQotLS0KCgojIFN0YXJ0dXAgCgpgYGB7ciwgbWVzc2FnZSA9IEZ9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoZ2dwbWlzYykKbGlicmFyeShoZXJlKQoKc291cmNlKGhlcmUoImhlbHBlcl9mdW5jdGlvbnMvZGF0YV9pbXBvcnRfZnVuY3Rpb25zLlIiKSkKc291cmNlKGhlcmUoImhlbHBlcl9mdW5jdGlvbnMvZmlndXJlX2Zvcm1hdF9mdW5jdGlvbnMuUiIpKQpzb3VyY2UoaGVyZSgiaGVscGVyX2Z1bmN0aW9ucy9jYWxjdWxhdGlvbl9mdW5jdGlvbnMuUiIpKQppc2JfcGF0aCA8LSBoZXJlKCJkYXRhL2lzYiIpCmlzYl9zYW1wbGVzIDwtIHJlYWRfdHN2KGhlcmUoImRhdGEvaXNiL2xvZ3MvcGFyYWxsZWwubG9nIikpICU+JSAKICBzZXBhcmF0ZShDb21tYW5kLCBpbnRvID0gYyhOQSwgInNhbXBsZSIpLCBzZXAgPSAiICIpICU+JSAKICBwdWxsKHNhbXBsZSkgJT4lIHVuaXF1ZSgpCmBgYAoKIyMjIEdldCByZWZlcmVuY2UgYWxsZWxlcwoKLSBHQ2gzOCByZWZlcmVuY2UgYWxsZWxlcyAocGVyIGh0dHBzOi8vd3d3LmViaS5hYy51ay9pcGQvaW1ndC9obGEvaGVscC9nZW5vbWljcy5odG1sKQotIFRvIGJlIHVzZWQgdG8gY2FsY3VsYXRlIGNvdmVyYWdlCgpgYGB7ciwgbWVzc2FnZSA9IEZ9CnJlZmVyZW5jZV9hbGxlbGVzIDwtIHJlYWRfdHN2KGhlcmUoInJlZmVyZW5jZXMvR0NoMzhfcmVmZXJlbmNlX2FsbGVsZXMudHh0IiksIGNvbF9uYW1lcyA9IEYpICU+JSBwdWxsKDEpCmdlbm9tZV9yZWdpb25fcmVmZXJlbmNlIDwtIGdldF9hbGxlbGVfbGVuZ3RoKHJlZmVyZW5jZV9hbGxlbGVzKQpgYGAKCiMjIyBHZXQgYXJjYXNITEEgYWxpZ25tZW50IHN0YXRzCgpgYGB7cn0KYXJjYXNfbG9nX2RpciA8LSBzcHJpbnRmKCIlcy9hcmNhc0hMQSIsIGlzYl9wYXRoKQphbGlnbm1lbnRfc3RhdHNfZGYgPC0gaGxhX21hcHBpbmdfc3RhdHNfaW1wb3J0KGlzYl9zYW1wbGVzLCBhcmNhc19sb2dfZGlyKQpgYGAKCiMjIyBJbXBvcnQgY2VsbCBjb3VudHMKCmBgYHtyfQpjZWxsX2NvdW50c19kZiA8LSByZWFkUkRTKGhlcmUoImRhdGEvaXNiL2lzYl9zZXF1ZW5jZWRfY2VsbF9jb3VudC5SRFMiKSkKYGBgCgojIyMgQXNzZW1ibGUgYWNjdXJhY3kgREYKCmBgYHtyfQpzdWNjZXNzX2RmIDwtIHJlYWRSRFMoaGVyZSgiMl9hY2N1cmFjeS9pc2Jfc3VjY2Vzcy5SRFMiKSkKYWNjdXJhY3lfZGYgPC0gcmVhZFJEUyhoZXJlKCIzX0RSQi9pc2JfYWNjdXJhY3lfZHJiMzQ1X2ZpbHRlcmVkLlJEUyIpKQphY2N1cmFjeV9kZiA8LSBhY2N1cmFjeV9kZiAlPiUgCiAgbGVmdF9qb2luKAogICAgc3VjY2Vzc19kZiAlPiUgc2VsZWN0KHNhbXBsZTpmaWVsZCwgZ2Vub3R5cGVyLCBzdWNjZXNzID0gYWNjdXJhY3kpLAogICAgYnkgPSBjKCJzYW1wbGUiLCAibG9jdXMiLCAiZmllbGQiLCAiZ2Vub3R5cGVyIikKICApJT4lIAogIGxlZnRfam9pbihhbGlnbm1lbnRfc3RhdHNfZGYsIGJ5ID0gYygic2FtcGxlIiwgImxvY3VzIikpICU+JSAKICBsZWZ0X2pvaW4oZ2Vub21lX3JlZ2lvbl9yZWZlcmVuY2UsIGJ5ID0gImxvY3VzIikgJT4lCiAgbGVmdF9qb2luKGNlbGxfY291bnRzX2RmLCBieSA9ICJzYW1wbGUiKSAlPiUKICBtdXRhdGVfYXQodmFycyhjKHJlYWRzLCBicCkpLCBhcy5udW1lcmljKSAlPiUgCiAgbXV0YXRlKGNvdmVyYWdlID0gKHJlYWRzICogOTEpL2JwKSAlPiUgCiAgbXV0YXRlKG5fYWxsZWxlcyA9IG1hcF9kYmwoYWxsZWxlLCBmdW5jdGlvbih4KSBzdW0oIWlzLm5hKHgpKSkpICU+JSAKICBmaWx0ZXIoZ3JlcGwoIl5bQUJDXXxELltBQl0xIiwgbG9jdXMpICYgZ3JlcGwoIi0oQUN8QkwpJCIsIHNhbXBsZSkgJiBnZW5vdHlwZXIgIT0gImhsYW1pbmVyIikgCmBgYAoKCiMjIyBDb3ZlcmFnZSBiYXNlZCBwbG90cwoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0yLjUsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2UoYWNjdXJhY3lfZGYsIHhfdmFyID0gImNvdmVyYWdlIiwgeV92YXIgPSAiYWNjdXJhY3kiKSAKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mi41LCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKGFjY3VyYWN5X2RmLCB4X3ZhciA9ICJjb3ZlcmFnZSIsIHlfdmFyID0gInN1Y2Nlc3MiKQpgYGAKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0zLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKGFjY3VyYWN5X2RmLCB4X3ZhciA9ICJjb3ZlcmFnZSIsIHlfdmFyID0gIm5fYWxsZWxlcyIsIGZhY2V0X2dlbm90eXBlciA9IFQpCmBgYAoKIyMjIENlbGwgbnVtYmVyIGJhc2VkIHBsb3RzCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTIuNSwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShhY2N1cmFjeV9kZiwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gImFjY3VyYWN5IikgCmBgYApgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTIuNSwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShhY2N1cmFjeV9kZiwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gInN1Y2Nlc3MiKQpgYGAKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0zLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKGFjY3VyYWN5X2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAibl9hbGxlbGVzIiwgZmFjZXRfZ2Vub3R5cGVyID0gVCkKYGBgCgoKIyBTdWJzYW1wbGUgUkVBRFMKCiMjIyBJbXBvcnQgcmVhZCBzdWJzYW1wbGUgZGF0YQoKYGBge3J9CiMgSW1wb3J0IHByZWRpY3RlZCBnZW5vdHlwZXMKc3Vic2FtcGxlX3JlYWRzX3BhdGggPC0gaGVyZSgiZGF0YS9pc2Ivc3Vic2FtcGxlIikKc3Vic2FtcGxlX3JlYWRzX3NhbXBsZXMgPC0gdGliYmxlKHNhbXBsZSA9IGxpc3QuZmlsZXMoc3ByaW50ZigiJXMvYXJjYXNITEEiLCBzdWJzYW1wbGVfcmVhZHNfcGF0aCkpKSAlPiUgCiAgZmlsdGVyKGdyZXBsKCJeSU5DT1YiLCBzYW1wbGUpKSAlPiUgCiAgc2VwYXJhdGUoc2FtcGxlLCBpbnRvID0gYygic2FtcGxlIiksIHNlcCA9ICJcXC4iLCBleHRyYSA9ICJkcm9wIikgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIHB1bGwoc2FtcGxlKQpzdWJzYW1wbGVfcmVhZHNfZGYgPC0gZm9ybWF0X2hsYV90YWJsZShjb21iaW5lX0hMQV9pbXBvcnQocGF0aCA9IHN1YnNhbXBsZV9yZWFkc19wYXRoLCBzYW1wbGVzID0gc3Vic2FtcGxlX3JlYWRzX3NhbXBsZXMpKQpzdWJzYW1wbGVfcmVhZHNfZGYgPC0gc3Vic2FtcGxlX3JlYWRzX2RmICU+JSAKICBmaWx0ZXIoZ3JlcGwoIl5bQUJDXXxELltBQl0xIiwgbG9jdXMpICYgZ3JlcGwoIi0oQUN8QkwpXyIsIHNhbXBsZSkpCnN1YnNhbXBsZV9yZWFkc19kZgpgYGAKCmBgYHtyLCBtZXNzYWdlID0gRn0KIyBFeHBhbmQgaW52aXRybyBnZW5vdHlwZXMgYWNyb3NzIHJlYWQgc3Vic2FtcGxlIG5hbWVzCmludml0cm9fZGYgPC0gaW52aXRyb19pbXBvcnQoKQppbnZpdHJvX3JlYWRzX2RmIDwtIHN1YnNhbXBsZV9yZWFkc19kZiAlPiUgCiAgc2VsZWN0KHNhbXBsZSkgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIHNlcGFyYXRlKHNhbXBsZSwgaW50byA9IGMoInNhbXBsZSIsICJzdWJzYW1wbGUiKSwgc2VwID0gIl8iKSAlPiUgCiAgbGVmdF9qb2luKGludml0cm9fZGYsIGJ5ID0gInNhbXBsZSIpICU+JSAKICB1bml0ZShzYW1wbGUsIHNhbXBsZSwgc3Vic2FtcGxlLCBzZXAgPSAiXyIpICU+JSAKICBmb3JtYXRfaGxhX3RhYmxlKCkgJT4lIAogIGRyb3BfbmEoKQppbnZpdHJvX3JlYWRzX2RmCmBgYAoKYGBge3J9CiMgSW1wb3J0IHJlYWQgc3RhdGlzdGljcwpzdWJzYW1wbGVfcmVhZHNfYXJjYXNfbG9nX2RpciA8LSBzcHJpbnRmKCIlcy9hcmNhc0hMQSIsIHN1YnNhbXBsZV9yZWFkc19wYXRoKQpzdWJzYW1wbGVfcmVhZHNfYWxpZ25tZW50X3N0YXRzX2RmIDwtIGhsYV9tYXBwaW5nX3N0YXRzX2ltcG9ydChzdWJzYW1wbGVfcmVhZHNfc2FtcGxlcywgc3Vic2FtcGxlX3JlYWRzX2FyY2FzX2xvZ19kaXIpCmBgYAoKIyMjIENhbGN1bGF0ZSBhY2N1cmFjeQoKYGBge3J9CiMgQ2FsY3VsYXRlIGFjY3VyYWN5CnN1YnNhbXBsZV9yZWFkc19hY2N1cmFjeV9kZiA8LSBjb21wYXJlX2hsYSgKICBobGFfZGYgPSBiaW5kX3Jvd3MoCiAgICBzdWJzYW1wbGVfcmVhZHNfZGYsCiAgICBpbnZpdHJvX3JlYWRzX2RmCiAgKSwKICByZWZlcmVuY2UgPSAiaW52aXRybyIsIAogIG1ldGhvZCA9ICJhY2N1cmFjeSIKKQojIHNhdmVSRFMoc3Vic2FtcGxlX3JlYWRzX2FjY3VyYWN5X2RmLCBoZXJlKCI1X2NvdmVyYWdlX2FjY3VyYWN5L2lzYl9zdWJzYW1wbGVfcmVhZHNfYWNjdXJhY3kuUkRTIikpCmBgYAoKCmBgYHtyfQojIENhbGN1bGF0ZSBzdWNjZXNzCnN1YnNhbXBsZV9yZWFkc19zdWNjZXNzX2RmIDwtIGNvbXBhcmVfaGxhKAogIGhsYV9kZiA9IGJpbmRfcm93cygKICAgIHN1YnNhbXBsZV9yZWFkc19kZiwKICAgIGludml0cm9fcmVhZHNfZGYKICApLAogIHJlZmVyZW5jZSA9ICJpbnZpdHJvIiwgCiAgbWV0aG9kID0gInN1Y2Nlc3MiCikKIyBzYXZlUkRTKHN1YnNhbXBsZV9yZWFkc19zdWNjZXNzX2RmLCBoZXJlKCI1X2NvdmVyYWdlX2FjY3VyYWN5L2lzYl9zdWJzYW1wbGVfcmVhZHNfc3VjY2Vzcy5SRFMiKSkKYGBgCgpgYGB7cn0KIyBDb21iaW5lIHZhcmlvdXMgZGF0YQpzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYgPC0gc3Vic2FtcGxlX3JlYWRzX2FjY3VyYWN5X2RmICU+JSAKICBsZWZ0X2pvaW4oCiAgICBzdWJzYW1wbGVfcmVhZHNfc3VjY2Vzc19kZiAlPiUgc2VsZWN0KHNhbXBsZTpmaWVsZCwgZ2Vub3R5cGVyLCBzdWNjZXNzID0gYWNjdXJhY3kpLAogICAgYnkgPSBjKCJzYW1wbGUiLCAibG9jdXMiLCAiZmllbGQiLCAiZ2Vub3R5cGVyIikKICApJT4lIAogIGxlZnRfam9pbihzdWJzYW1wbGVfcmVhZHNfYWxpZ25tZW50X3N0YXRzX2RmLCBieSA9IGMoInNhbXBsZSIsICJsb2N1cyIpKSAlPiUgCiAgbGVmdF9qb2luKGdlbm9tZV9yZWdpb25fcmVmZXJlbmNlLCBieSA9ICJsb2N1cyIpICU+JQogIGJpbmRfcm93cyhhY2N1cmFjeV9kZiAlPiUgc2VsZWN0KC1uX2NlbGxzKSkgJT4lICMgTm8gY2VsbCBudW1iZXJzIGZvciByZWFkIHN1YnNhbXBsZXMKICBtdXRhdGVfYXQodmFycyhjKHJlYWRzLCBicCkpLCBhcy5udW1lcmljKSAlPiUgCiAgbXV0YXRlKGNvdmVyYWdlID0gKHJlYWRzICogOTEpL2JwKSAlPiUgICMgQ2FsY3VsYXRlIGNvdmVyYWdlCiAgbXV0YXRlKG5fYWxsZWxlcyA9IG1hcF9kYmwoYWxsZWxlLCBmdW5jdGlvbih4KSBzdW0oIWlzLm5hKHgpKSkpICU+JSAgIyBDYWxjdWxhdGUgbl9hbGxlbGVzCiAgZmlsdGVyKGdyZXBsKCJeW0FCQ118RC5bQUJdMSIsIGxvY3VzKSAmIGdyZXBsKCItKEFDfEJMKSIsIHNhbXBsZSkgJiBnZW5vdHlwZXIgIT0gImhsYW1pbmVyIikgCiMgc2F2ZVJEUyhzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYsIGhlcmUoIjVfY292ZXJhZ2VfYWNjdXJhY3kvc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLlJEUyIpKQojIHN1YnNhbXBsZV9yZWFkc19jb21iaW5lZF9kZiA8LSByZWFkUkRTKGhlcmUoIjVfY292ZXJhZ2VfYWNjdXJhY3kvc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLlJEUyIpKQpgYGAKCiMjIyBSZWFkcyBwbG90cwpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTIuNSwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYsIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAiYWNjdXJhY3kiKSAKcGx0X3JlYWRfYWNjdXJhY3lfYWxsIDwtIGdnX2NvdmVyYWdlKHN1YnNhbXBsZV9yZWFkc19jb21iaW5lZF9kZiwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpIApwbHRfcmVhZF9hY2N1cmFjeV9hYmMgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmICU+JSBmaWx0ZXIoZ3JlcGwoIl5bQUJDXSIsIGxvY3VzKSksIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAiYWNjdXJhY3kiKSAKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mi41LCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKHN1YnNhbXBsZV9yZWFkc19jb21iaW5lZF9kZiwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJzdWNjZXNzIikKcGx0X3JlYWRfc3VjY2Vzc19hbGwgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gInN1Y2Nlc3MiKQpwbHRfcmVhZF9zdWNjZXNzX2FiYyA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYgJT4lIGZpbHRlcihncmVwbCgiXltBQkNdIiwgbG9jdXMpKSwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJzdWNjZXNzIikgCmBgYApgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTMsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gIm5fYWxsZWxlcyIsIGZhY2V0X2dlbm90eXBlciA9IFQpCnBsdF9yZWFkX2FsbGVsZV9hbGwgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gIm5fYWxsZWxlcyIsIGZhY2V0X2dlbm90eXBlciA9IFQpCnBsdF9yZWFkX2FsbGVsZV9hYmMgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX3JlYWRzX2NvbWJpbmVkX2RmICU+JSBmaWx0ZXIoZ3JlcGwoIl5bQUJDXSIsIGxvY3VzKSksIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAibl9hbGxlbGVzIiwgZmFjZXRfZ2Vub3R5cGVyID0gVCkKYGBgCi0gRGVmYXVsdCBhcmNhc0hMQSBjdXQgb2ZmIDc1IHJlYWRzIChsb2cxMCA9IDEuOCkKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYgJT4lIAogIGZpbHRlcihmaWVsZCA9PSAiZmllbGRfMiIpICU+JSAKICBtdXRhdGUobl9hbGxlbGVzID0gZmFjdG9yKG5fYWxsZWxlcywgbGV2ZWxzID0gMDoyKSkgJT4lIAogIGdncGxvdChhZXMoeSA9IG5fYWxsZWxlcywgeCA9IGxvZzEwKGNvdmVyYWdlKSkpKwogICMgZ2VvbV92aW9saW4oc2NhbGUgPSAiY291bnQiLCBhbHBoYSA9IDAuNSwgKSsKICBnZW9tX2ppdHRlcihzaXplID0gMC4yLCB3aWR0aCA9IDAsIGhlaWdodCA9MC4yLCBhbHBoYSA9IDAuMikrCiAgIyBnZW9tX2JveHBsb3Qod2lkdGg9MC4xKSsKICAjIGdnYmVlc3dhcm06Omdlb21fYmVlc3dhcm0oc2l6ZSA9IDAuMSwgYWxwaGEgPSAwLjEpKwogICMgY29vcmRfZmxpcCgpKwogIGZhY2V0X2dyaWQoZ2Vub3R5cGVyIH4gbG9jdXMsIHNjYWxlcyA9ICJmcmVlIikrCiAgdGhlbWVfYncoKQpgYGAKCiMgU3Vic2FtcGxlIENFTExTCgpgYGB7cn0KIyBJbXBvcnQgcHJlZGljdGVkIGdlbm90eXBlcwpzdWJzYW1wbGVfY2VsbHNfcGF0aCA8LSBoZXJlKCJkYXRhL2lzYi9zdWJzYW1wbGVfY2VsbHMiKQpzdWJzYW1wbGVfY2VsbHNfc2FtcGxlcyA8LSB0aWJibGUoc2FtcGxlID0gbGlzdC5maWxlcyhzcHJpbnRmKCIlcy9hcmNhc0hMQSIsIHN1YnNhbXBsZV9jZWxsc19wYXRoKSkpICU+JSAKICBmaWx0ZXIoZ3JlcGwoIl5JTkNPViIsIHNhbXBsZSkpICU+JSAKICBzZXBhcmF0ZShzYW1wbGUsIGludG8gPSBjKCJzYW1wbGUiKSwgc2VwID0gIlxcLiIsIGV4dHJhID0gImRyb3AiKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgcHVsbChzYW1wbGUpCnN1YnNhbXBsZV9jZWxsc19kZiA8LSBmb3JtYXRfaGxhX3RhYmxlKGNvbWJpbmVfSExBX2ltcG9ydChwYXRoID0gc3Vic2FtcGxlX2NlbGxzX3BhdGgsIHNhbXBsZXMgPSBzdWJzYW1wbGVfY2VsbHNfc2FtcGxlcykpCnN1YnNhbXBsZV9jZWxsc19kZiA8LSBzdWJzYW1wbGVfY2VsbHNfZGYgJT4lIAogIGZpbHRlcihncmVwbCgiXltBQkNdfEQuW0FCXTEiLCBsb2N1cykgJiBncmVwbCgiLShBQ3xCTClfIiwgc2FtcGxlKSkKc3Vic2FtcGxlX2NlbGxzX2RmCmBgYAoKCmBgYHtyLCBtZXNzYWdlID0gRn0KIyBFeHBhbmQgaW52aXRybyBnZW5vdHlwZXMgYWNyb3NzIHJlYWQgc3Vic2FtcGxlIG5hbWVzCmludml0cm9fZGYgPC0gaW52aXRyb19pbXBvcnQoKQppbnZpdHJvX2NlbGxzX2RmIDwtIHN1YnNhbXBsZV9jZWxsc19kZiAlPiUgCiAgc2VsZWN0KHNhbXBsZSkgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIHNlcGFyYXRlKHNhbXBsZSwgaW50byA9IGMoInNhbXBsZSIsICJzdWJzYW1wbGUiKSwgc2VwID0gIl8iKSAlPiUgCiAgbGVmdF9qb2luKGludml0cm9fZGYsIGJ5ID0gInNhbXBsZSIpICU+JSAKICB1bml0ZShzYW1wbGUsIHNhbXBsZSwgc3Vic2FtcGxlLCBzZXAgPSAiXyIpICU+JSAKICBmb3JtYXRfaGxhX3RhYmxlKCkgJT4lIAogIGRyb3BfbmEoKQppbnZpdHJvX2NlbGxzX2RmCmBgYAoKYGBge3J9CiMgSW1wb3J0IHJlYWQgc3RhdGlzdGljcwpzdWJzYW1wbGVfY2VsbHNfYXJjYXNfbG9nX2RpciA8LSBzcHJpbnRmKCIlcy9hcmNhc0hMQSIsIHN1YnNhbXBsZV9jZWxsc19wYXRoKQpzdWJzYW1wbGVfY2VsbHNfYWxpZ25tZW50X3N0YXRzX2RmIDwtIGhsYV9tYXBwaW5nX3N0YXRzX2ltcG9ydChzdWJzYW1wbGVfY2VsbHNfc2FtcGxlcywgc3Vic2FtcGxlX2NlbGxzX2FyY2FzX2xvZ19kaXIpCmBgYAoKYGBge3J9CiMgSW1wb3J0IGNlbGwgY291bnRzIGZvciBlYWNoIHN1YnNhbXBsZQpzdWJzYW1wbGVfY2VsbF9jb3VudHNfZGYgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YS9pc2Ivc3Vic2FtcGxlX2NlbGxzL3N1YnNhbXBsZV9jZWxsX2NvdW50cy5jc3YiKSkKYGBgCgojIyMgQ2FsY3VsYXRlIGFjY3VyYWN5CgpgYGB7cn0KIyBDYWxjdWxhdGUgYWNjdXJhY3kKc3Vic2FtcGxlX2NlbGxzX2FjY3VyYWN5X2RmIDwtIGNvbXBhcmVfaGxhKAogIGhsYV9kZiA9IGJpbmRfcm93cygKICAgIHN1YnNhbXBsZV9jZWxsc19kZiwKICAgIGludml0cm9fY2VsbHNfZGYKICApLAogIHJlZmVyZW5jZSA9ICJpbnZpdHJvIiwgCiAgbWV0aG9kID0gImFjY3VyYWN5IgopCiMgc2F2ZVJEUyhzdWJzYW1wbGVfY2VsbHNfYWNjdXJhY3lfZGYsIGhlcmUoIjVfY292ZXJhZ2VfYWNjdXJhY3kvaXNiX3N1YnNhbXBsZV9jZWxsc19hY2N1cmFjeS5SRFMiKSkKIyBzdWJzYW1wbGVfY2VsbHNfYWNjdXJhY3lfZGYgPC0gcmVhZFJEUyhoZXJlKCI1X2NvdmVyYWdlX2FjY3VyYWN5L2lzYl9zdWJzYW1wbGVfY2VsbHNfYWNjdXJhY3kuUkRTIikpCmBgYAoKYGBge3J9CiMgQ2FsY3VsYXRlIHN1Y2Nlc3MKc3Vic2FtcGxlX2NlbGxzX3N1Y2Nlc3NfZGYgPC0gY29tcGFyZV9obGEoCiAgaGxhX2RmID0gYmluZF9yb3dzKAogICAgc3Vic2FtcGxlX2NlbGxzX2RmLAogICAgaW52aXRyb19jZWxsc19kZgogICksCiAgcmVmZXJlbmNlID0gImludml0cm8iLCAKICBtZXRob2QgPSAic3VjY2VzcyIKKQojIHNhdmVSRFMoc3Vic2FtcGxlX2NlbGxzX3N1Y2Nlc3NfZGYsIGhlcmUoIjVfY292ZXJhZ2VfYWNjdXJhY3kvaXNiX3N1YnNhbXBsZV9jZWxsc19zdWNjZXNzLlJEUyIpKQojIHN1YnNhbXBsZV9jZWxsc19zdWNjZXNzX2RmIDwtIHJlYWRSRFMoaGVyZSgiNV9jb3ZlcmFnZV9hY2N1cmFjeS9pc2Jfc3Vic2FtcGxlX2NlbGxzX3N1Y2Nlc3MuUkRTIikpCmBgYAoKYGBge3J9CiMgQ29tYmluZSB2YXJpb3VzIGRhdGEKc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmIDwtIHN1YnNhbXBsZV9jZWxsc19hY2N1cmFjeV9kZiAlPiUgCiAgbGVmdF9qb2luKAogICAgc3Vic2FtcGxlX2NlbGxzX3N1Y2Nlc3NfZGYgJT4lIHNlbGVjdChzYW1wbGU6ZmllbGQsIGdlbm90eXBlciwgc3VjY2VzcyA9IGFjY3VyYWN5KSwKICAgIGJ5ID0gYygic2FtcGxlIiwgImxvY3VzIiwgImZpZWxkIiwgImdlbm90eXBlciIpCiAgKSU+JSAKICBsZWZ0X2pvaW4oc3Vic2FtcGxlX2NlbGxzX2FsaWdubWVudF9zdGF0c19kZiwgYnkgPSBjKCJzYW1wbGUiLCAibG9jdXMiKSkgJT4lIAogIGxlZnRfam9pbihnZW5vbWVfcmVnaW9uX3JlZmVyZW5jZSwgYnkgPSAibG9jdXMiKSAlPiUKICBsZWZ0X2pvaW4oc3Vic2FtcGxlX2NlbGxfY291bnRzX2RmLCBieSA9ICJzYW1wbGUiKSAlPiUKICBiaW5kX3Jvd3MoYWNjdXJhY3lfZGYpICU+JSAKICBtdXRhdGVfYXQodmFycyhjKHJlYWRzLCBicCkpLCBhcy5udW1lcmljKSAlPiUgCiAgbXV0YXRlKGNvdmVyYWdlID0gKHJlYWRzICogOTEpL2JwKSAlPiUgCiAgbXV0YXRlKG5fYWxsZWxlcyA9IG1hcF9kYmwoYWxsZWxlLCBmdW5jdGlvbih4KSBzdW0oIWlzLm5hKHgpKSkpICU+JSAKICBmaWx0ZXIoZ3JlcGwoIl5bQUJDXXxELltBQl0xIiwgbG9jdXMpICYgZ3JlcGwoIi0oQUN8QkwpIiwgc2FtcGxlKSAmIGdlbm90eXBlciAhPSAiaGxhbWluZXIiKSAKIyBzYXZlUkRTKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiwgaGVyZSgiNV9jb3ZlcmFnZV9hY2N1cmFjeS9zdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYuUkRTIikpCmBgYAoKIyMjIENvdmVyYWdlIHBsb3RzCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTIuNSwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gImNvdmVyYWdlIiwgeV92YXIgPSAiYWNjdXJhY3kiKSAKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mi41LCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiwgeF92YXIgPSAiY292ZXJhZ2UiLCB5X3ZhciA9ICJzdWNjZXNzIikKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQpnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gImNvdmVyYWdlIiwgeV92YXIgPSAibl9hbGxlbGVzIiwgZmFjZXRfZ2Vub3R5cGVyID0gVCkKYGBgCgojIyMgQ2VsbCBudW1iZXIgcGxvdHMKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mi41LCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gImFjY3VyYWN5IikgCnBsdF9jZWxsX2FjY3VyYWN5X2FsbCA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gIm5fY2VsbHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpIApwbHRfY2VsbF9hY2N1cmFjeV9hYmMgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmICU+JSBmaWx0ZXIoZ3JlcGwoIl5bQUJDXSIsIGxvY3VzKSksIHhfdmFyID0gIm5fY2VsbHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpIApgYGAKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0yLjUsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0KZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAic3VjY2VzcyIpIApwbHRfY2VsbF9zdWNjZXNzX2FsbCA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gIm5fY2VsbHMiLCB5X3ZhciA9ICJzdWNjZXNzIikgCnBsdF9jZWxsX3N1Y2Nlc3NfYWJjIDwtIGdnX2NvdmVyYWdlKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiAlPiUgZmlsdGVyKGdyZXBsKCJeW0FCQ10iLCBsb2N1cykpLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAic3VjY2VzcyIpIApgYGAKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD0zLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9CmdnX2NvdmVyYWdlKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gIm5fYWxsZWxlcyIsIGZhY2V0X2dlbm90eXBlciA9IFQpCnBsdF9jZWxsX2FsbGVsZV9hbGwgPC0gZ2dfY292ZXJhZ2Uoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAibl9hbGxlbGVzIiwgZmFjZXRfZ2Vub3R5cGVyID0gVCkKcGx0X2NlbGxfYWxsZWxlX2FiYyA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYgJT4lIGZpbHRlcihncmVwbCgiXltBQkNdIiwgbG9jdXMpKSwgeF92YXIgPSAibl9jZWxscyIsIHlfdmFyID0gIm5fYWxsZWxlcyIsIGZhY2V0X2dlbm90eXBlciA9IFQpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Mywgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQojIHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiAlPiUgCiMgICBtdXRhdGUocmVhZHMgPSByZWFkcy9uX2NlbGxzKSAlPiUgCiMgICBmaWx0ZXIocmVhZHMgPCAxMDApICU+JSAKIyAgIGdnX2NvdmVyYWdlKHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAiYWNjdXJhY3kiLCB4X2xvZyA9IEYpIApgYGAKCgoKCgoKCgojIENvbWJpbmVkIHBsb3RzCmBgYHtyLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNywgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGfQpub19sZWcgPC0gbGlzdCh0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKQpsZWdlbmQgPC0gY293cGxvdDo6Z2V0X2xlZ2VuZChwbHRfcmVhZF9hY2N1cmFjeV9hYmMpCnBsb3RfZ3JpZCgKICBwbG90X2dyaWQoCiAgICBwbHRfcmVhZF9hY2N1cmFjeV9hYmMgKyBub19sZWcsCiAgICBwbHRfcmVhZF9zdWNjZXNzX2FiYyArIG5vX2xlZywKICAgIHBsdF9yZWFkX2FsbGVsZV9hYmMsCiAgICBuY29sID0gMSwKICAgIGFsaWduID0gInYiLAogICAgYXhpcyA9ICJsciIsCiAgICByZWxfaGVpZ2h0cyA9IGMoMSwxLDEuMiksCiAgICBsYWJlbHMgPSBMRVRURVJTWzE6M10KICApLAogIHBsb3RfZ3JpZCgKICAgIHBsdF9jZWxsX2FjY3VyYWN5X2FiYyArIG5vX2xlZywKICAgIHBsdF9jZWxsX3N1Y2Nlc3NfYWJjICsgbm9fbGVnLAogICAgcGx0X2NlbGxfYWxsZWxlX2FiYywKICAgIG5jb2wgPSAxLAogICAgYWxpZ24gPSAidiIsCiAgICBheGlzID0gImxyIiwKICAgIHJlbF9oZWlnaHRzID0gYygxLDEsMS4yKSwKICAgIGxhYmVscyA9IExFVFRFUlNbNDo2XQogICksCiAgcGxvdF9ncmlkKAogICAgbGVnZW5kLAogICAgbGVnZW5kLAogICAgTkEsCiAgICBuY29sID0gMQogICksCiAgbnJvdyA9IDEsCiAgcmVsX3dpZHRocyA9IGMoMSwxLDAuMjUpCikKYGBgCgpgYGB7ciwgZmlnLndpZHRoID0gMTgsIGZpZy5oZWlnaHQgPSA3LCBtZXNzYWdlID0gRiwgd2FybmluZyA9IEZ9Cm5vX2xlZyA8LSBsaXN0KHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikpCmxlZ2VuZCA8LSBjb3dwbG90OjpnZXRfbGVnZW5kKHBsdF9yZWFkX2FjY3VyYWN5X2FsbCkKcGxvdF9ncmlkKAogIHBsb3RfZ3JpZCgKICAgIHBsdF9yZWFkX2FjY3VyYWN5X2FsbCArIG5vX2xlZywKICAgIHBsdF9yZWFkX3N1Y2Nlc3NfYWxsICsgbm9fbGVnLAogICAgcGx0X3JlYWRfYWxsZWxlX2FsbCwKICAgIG5jb2wgPSAxLAogICAgYWxpZ24gPSAidiIsCiAgICBheGlzID0gImxyIiwKICAgIHJlbF9oZWlnaHRzID0gYygxLDEsMS4yKSwKICAgIGxhYmVscyA9IExFVFRFUlNbMTozXQogICksCiAgcGxvdF9ncmlkKAogICAgcGx0X2NlbGxfYWNjdXJhY3lfYWxsICsgbm9fbGVnLAogICAgcGx0X2NlbGxfc3VjY2Vzc19hbGwgKyBub19sZWcsCiAgICBwbHRfY2VsbF9hbGxlbGVfYWxsLAogICAgbmNvbCA9IDEsCiAgICBhbGlnbiA9ICJ2IiwKICAgIGF4aXMgPSAibHIiLAogICAgcmVsX2hlaWdodHMgPSBjKDEsMSwxLjIpLAogICAgbGFiZWxzID0gTEVUVEVSU1s0OjZdCiAgKSwKICBwbG90X2dyaWQoCiAgICBsZWdlbmQsCiAgICBsZWdlbmQsCiAgICBOQSwKICAgIG5jb2wgPSAxCiAgKSwKICBucm93ID0gMSwKICByZWxfd2lkdGhzID0gYygxLDEsMC4yNSkKKQpgYGAKCiMjIyBNYWluIHBsb3QKCmBgYHtyfQpsb2NpIDwtIGMoIkEiLCAiQiIsICJDIiwgIkRQQjEiLCAiRFFBMSIsICJEUkIxIikKcGx0X3JlYWRfYWNjdXJhY3lfc3Vic2V0IDwtIGdnX2NvdmVyYWdlKAogIHN1YnNhbXBsZV9yZWFkc19jb21iaW5lZF9kZiAlPiUgCiAgICBmaWx0ZXIobG9jdXMgJWluJSBsb2NpKSAlPiUgCiAgICBmaWx0ZXIoIShnZW5vdHlwZXIgPT0gInBobGF0IiAmIGxvY3VzID09ICJEUEIxIikpICU+JSAKICAgIGZpbHRlcighKGdlbm90eXBlciA9PSAib3B0aXR5cGUiICYgbG9jdXMgPT0gIkRQQjEiKSkgJT4lIAogICAgZmlsdGVyKCEoZ2Vub3R5cGVyID09ICJvcHRpdHlwZSIgJiBsb2N1cyA9PSAiRFFBMSIpKSAlPiUgCiAgICBmaWx0ZXIoIShnZW5vdHlwZXIgPT0gIm9wdGl0eXBlIiAmIGxvY3VzID09ICJEUkIxIikpLCAKICB4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gImFjY3VyYWN5IikgKwogIGZhY2V0X3dyYXAofmxvY3VzLCBucm93ID0gMikKcGx0X3JlYWRfYWNjdXJhY3lfc3Vic2V0CmBgYApgYGB7cn0Kc2F2ZV9wbG90KGhlcmUoImZpZ3VyZXNfcGRmL3YyLzVfY292ZXJhZ2UucGRmIiksIHBsdF9yZWFkX2FjY3VyYWN5X3N1YnNldCwgYmFzZV9oZWlnaHQgPSA0LCBiYXNlX3dpZHRoID0gNikKYGBgCgpgYGB7cn0KcGx0X3JlYWRfYWxsZWxlX2FsbCA8LSBnZ19jb3ZlcmFnZShzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYgJT4lIAogICAgZmlsdGVyKGxvY3VzICVpbiUgbG9jaSkgJT4lIAogICAgZmlsdGVyKCEoZ2Vub3R5cGVyID09ICJwaGxhdCIgJiBsb2N1cyA9PSAiRFBCMSIpKSAlPiUgCiAgICBmaWx0ZXIoIShnZW5vdHlwZXIgPT0gIm9wdGl0eXBlIiAmIGxvY3VzID09ICJEUEIxIikpICU+JSAKICAgIGZpbHRlcighKGdlbm90eXBlciA9PSAib3B0aXR5cGUiICYgbG9jdXMgPT0gIkRRQTEiKSkgJT4lIAogICAgZmlsdGVyKCEoZ2Vub3R5cGVyID09ICJvcHRpdHlwZSIgJiBsb2N1cyA9PSAiRFJCMSIpKSwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJuX2FsbGVsZXMiLCBmYWNldF9nZW5vdHlwZXIgPSBUKQpwbHRfcmVhZF9hbGxlbGVfYWxsCmBgYApgYGB7ciwgZmlnLndpZHRoID0gNywgZmlnLmhlaWdodD03fQpwbHRfbWFpbiA8LSBwbG90X2dyaWQoCiAgcGx0X3JlYWRfYWNjdXJhY3lfc3Vic2V0LAogIHBsdF9yZWFkX2FsbGVsZV9hbGwsCiAgbmNvbCA9IDEsCiAgcmVsX2hlaWdodHMgPSBjKDMsMiksCiAgYWxpZ24gPSAidiIsCiAgYXhpcyA9ICJsciIsCiAgbGFiZWxzID0gYygiQSIsICJCIikKKQpwbHRfbWFpbgpgYGAKYGBge3J9CnNhdmVfcGxvdChoZXJlKCJmaWd1cmVzX3BkZi92Mi81X2NvdmVyYWdlLnBkZiIpLCBwbHRfbWFpbiwgYmFzZV9oZWlnaHQgPSA3LCBiYXNlX3dpZHRoID0gNykKYGBgCgojIFNsb3BlIHN0YXRzCgpgYGB7cn0KZ2V0X2xtX3N0YXRzIDwtIGZ1bmN0aW9uKGRmLCB4X3ZhciA9ICJjb3ZlcmFnZSIsIHlfdmFyID0gImFjY3VyYWN5IiwgZmllbGRfdmFyID0gImZpZWxkXzIiLCB4X2xvZyA9IFQpewogICMgSW5wdXQgY2hlY2tzCiAgYXJnX2NvbCA8LSBtYWtlQXNzZXJ0Q29sbGVjdGlvbigpCiAgYXNzZXJ0Q2hvaWNlKHlfdmFyLCBjKCJhY2N1cmFjeSIsICJzdWNjZXNzIiwgIm5fYWxsZWxlcyIpLCBhZGQgPSBhcmdfY29sKQogIGFzc2VydENob2ljZSh4X3ZhciwgYygicmVhZHMiLCAiY292ZXJhZ2UiLCAibl9jZWxscyIpLCBhZGQgPSBhcmdfY29sKQogIGFzc2VydENob2ljZShmaWVsZF92YXIsIGMoImZpZWxkXzEiLCAiZmllbGRfMiIsICJmaWVsZF8zIiksIGFkZCA9IGFyZ19jb2wpCiAgYXNzZXJ0TG9naWNhbCh4X2xvZywgYWRkID0gYXJnX2NvbCkKICBpZiAoYXJnX2NvbCRpc0VtcHR5KCk9PUYpIHttYXAoYXJnX2NvbCRnZXRNZXNzYWdlcygpLHByaW50KTtyZXBvcnRBc3NlcnRpb25zKGFyZ19jb2wpfQogIAogICMgYnJvd3NlcigpCiAgZGYgPC0gZGYgJT4lIAogICAgZmlsdGVyKGZpZWxkID09IGZpZWxkX3ZhcikgJT4lIAogICAgZXhjbHVkZV9nZW5vdHlwZXJfZmllbGRzKCkgIyBSZXBsYWNlIHcvIGV4Y2x1ZGVfZ2Vub3R5cGVyX2ZpZWxkcz8KICBpZiAoeF9sb2cgPT1UKXtkZiA8LSBkZiAlPiUgbXV0YXRlX2F0KHhfdmFyLCBsb2cxMCl9CiAgZGYgJT4lCiAgZmlsdGVyX2F0KHhfdmFyLCBmdW5jdGlvbih4KSAhaXMubmEoeCkgJiAhaXMuaW5maW5pdGUoeCkpICU+JSAKICBncm91cF9ieShsb2N1cywgZmllbGQsIGdlbm90eXBlcikgJT4lCiAgbmVzdCgpICU+JQogIG11dGF0ZShkYXRhID0gbWFwKGRhdGEsIGZ1bmN0aW9uKHgpewogICAgc3VtbWFyeShsbSghIXN5bSh5X3ZhcikgfiAhIXN5bSh4X3ZhciksIGRhdGEgPSB4KSkgJT4lIGJyb29tOjp0aWR5KCkgJT4lIGZpbHRlcih0ZXJtID09IHhfdmFyKQogIH0pKSAlPiUgdW5uZXN0X3dpZGVyKGRhdGEpICU+JQogIG11dGF0ZShlc3RfbWluID0gcm91bmQoZXN0aW1hdGUgLSAyKnN0ZC5lcnJvciwgMiksCiAgICAgICAgIGVzdF9tYXggPSByb3VuZChlc3RpbWF0ZSArIDIqc3RkLmVycm9yLCAyKSkKfQoKbW9kZWxfc3RhdHMgPC0gZ2V0X2xtX3N0YXRzKHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiwgeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIsIHhfbG9nID0gVCkKbW9kZWxfc3RhdHMKYGBgCgpgYGB7cn0KbW9kZWxfc3RhdHMgPC0gYmluZF9yb3dzKAogIGdldF9sbV9zdGF0cyhzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYsIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAiYWNjdXJhY3kiLCB4X2xvZyA9IFQpICU+JSBtdXRhdGUoeF92YXIgPSAicmVhZHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpLAogIGdldF9sbV9zdGF0cyhzdWJzYW1wbGVfcmVhZHNfY29tYmluZWRfZGYsIHhfdmFyID0gInJlYWRzIiwgeV92YXIgPSAic3VjY2VzcyIsIHhfbG9nID0gVCkgJT4lIG11dGF0ZSh4X3ZhciA9ICJyZWFkcyIsIHlfdmFyID0gInN1Y2Nlc3MiKSwKICBnZXRfbG1fc3RhdHMoc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmLCB4X3ZhciA9ICJuX2NlbGxzIiwgeV92YXIgPSAiYWNjdXJhY3kiLCB4X2xvZyA9IFQpICU+JSBtdXRhdGUoeF92YXIgPSAiY2VsbHMiLCB5X3ZhciA9ICJhY2N1cmFjeSIpLAogIGdldF9sbV9zdGF0cyhzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYsIHhfdmFyID0gIm5fY2VsbHMiLCB5X3ZhciA9ICJzdWNjZXNzIiwgeF9sb2cgPSBUKSAlPiUgbXV0YXRlKHhfdmFyID0gImNlbGxzIiwgeV92YXIgPSAic3VjY2VzcyIpCikgICU+JSAKICAjIGZpbHRlcihncmVwbCgiXltBQkNdIiwgbG9jdXMpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoZmllbGQgPT0gImZpZWxkXzIiKSAKYGBgCgoKCiMgVGFibGUKYGBge3J9CmNvbF92YXJzIDwtIGMoInhfdmFyIiwgImxvY3VzIikKcm93X3ZhcnMgPC0gYygieV92YXIiLCAiZ2Vub3R5cGVyIikKCmZsZXhfZGYgPC0gbW9kZWxfc3RhdHMgJT4lIAogICMgZmlsdGVyKGdyZXBsKCJeW0FCQ10iLCBsb2N1cykpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihmaWVsZCA9PSAiZmllbGRfMiIpICU+JSAKICBtdXRhdGUoQ0kgPSBzcHJpbnRmKCIoJXMpIC0gKCVzKSIsIGVzdF9taW4sIGVzdF9tYXgpKSAlPiUgCiAgbXV0YXRlKGdlbm90eXBlciA9IHJlZm9ybWF0X2hsYV9nZW5vdHlwZXIoZ2Vub3R5cGVyKSkgJT4lIAogIHNlbGVjdChnZW5vdHlwZXIsIGxvY3VzLCBDSSwgeF92YXIsIHlfdmFyKSAlPiUgCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGNvbF92YXJzLCB2YWx1ZXNfZnJvbSA9ICJDSSIsIG5hbWVzX3NlcCA9ICAiLSIpIAoKZGZfa2V5IDwtIHRpYmJsZShjb2xfa2V5cyA9IG5hbWVzKGZsZXhfZGYpKSAlPiUgCiAgZmlsdGVyKCEoY29sX2tleXMgJWluJSBjKGNvbF92YXJzLCByb3dfdmFycykpKSAlPiUgCiAgc2VwYXJhdGUoY29sX2tleXMsIGludG8gPSBjb2xfdmFycywgc2VwID0gIi0iLCByZW1vdmUgPSBGKSAlPiUKICBtdXRhdGVfYXQodmFycyhjb250YWlucygiZ2Vub3R5cGVyIikpLCByZWZvcm1hdF9obGFfZ2Vub3R5cGVyKSAlPiUgCiAgYXJyYW5nZV9hdChjb2xfdmFycykgJT4lIAogIG11dGF0ZV9hbGwoYXMuY2hhcmFjdGVyKSAlPiUgCiAgbXV0YXRlX2F0KGNvbF92YXJzWyEoY29sX3ZhcnMgJWluJSAibG9jdXMiKV0sIHN0cl90b19zZW50ZW5jZSkKCm91dHB1dF90YWJsZSA8LSBmbGV4X2RmICU+JSAKICBzZWxlY3Qocm93X3ZhcnMsIGV2ZXJ5dGhpbmcoKSkgJT4lIAogIG11dGF0ZV9hdChyb3dfdmFyc1shKHJvd192YXJzICVpbiUgImdlbm90eXBlciIpXSwgc3RyX3RvX3NlbnRlbmNlKSAlPiUgCiAgIyBzZWxlY3QobG9jdXMsIGRmX2tleSRjb2xfa2V5cykgJT4lIAogIGZsZXh0YWJsZSgpICU+JSAKICBjb2xmb3JtYXRfY2hhcihuYV9zdHIgPSAiLS0tIikgJT4lCiAgbWVyZ2VfdihqPTE6MikgJT4lIAogIHNldF9oZWFkZXJfZGYobWFwcGluZyA9IGRmX2tleSwga2V5ID0gImNvbF9rZXlzIikgJT4lIAogIG1lcmdlX2gocGFydCA9ICJoZWFkZXIiKSAlPiUKICB0aGVtZV92YW5pbGxhKCkgJT4lIAogICMgdmxpbmUoaj12bGluZXNfc2VxdWVuY2UsIGJvcmRlciA9IGZwX2JvcmRlcl9kZWZhdWx0KCkpICU+JQogIGZpeF9ib3JkZXJfaXNzdWVzKCkgJT4lIAogIGF1dG9maXQoKSAlPiUgCiAgZm9udHNpemUoc2l6ZSA9IDgsIHBhcnQgPSAiYWxsIikgCgpwcmludChvdXRwdXRfdGFibGUpCiMgb3V0cHV0X3RhYmxlICU+JSBwcmludChwcmV2aWV3ID0gInBwdHgiKQpgYGAKCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSAgIGRmIDwtIGRmICU+JSAgLS0+CjwhLS0gICAgIG11dGF0ZShmaWVsZCA9IHJlZm9ybWF0X2hsYV9maWVsZChmaWVsZCkpICU+JSAgLS0+CjwhLS0gICAgIG11dGF0ZV9hdCh2YXJzKGNvbnRhaW5zKCJnZW5vdHlwZXIiKSksIHJlZm9ybWF0X2hsYV9nZW5vdHlwZXIpICU+JSAgLS0+CjwhLS0gICAgIG11dGF0ZShjZWxsX3ZhbHVlID0gaWZlbHNlKCFpcy5uYShzZSksICAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaW50ZigiJXMgJXMgJXMiLCByb3VuZChtZWFuX2FjY3VyYWN5LDIpLCJcdTAwQjEiLHJvdW5kKHNlLDIpKSwgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcmludGYoIiVzIiwgcm91bmQobWVhbl9hY2N1cmFjeSwyKSkpKSAlPiUgLS0+CjwhLS0gICAgIG11dGF0ZShjZWxsX3ZhbHVlID0gaWZlbHNlKGdyZXBsKCJOQSIsIGNlbGxfdmFsdWUpLCBOQSwgY2VsbF92YWx1ZSkpICU+JSAgLS0+CjwhLS0gICAgIHNlbGVjdCgtc2QsLXNlLCAtbWVhbl9hY2N1cmFjeSkgJT4lICAtLT4KPCEtLSAgICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG5lc3RpbmdfdmFycywgdmFsdWVzX2Zyb20gPSAiY2VsbF92YWx1ZSIsIG5hbWVzX3NlcCA9ICItIikgIC0tPgoKPCEtLSAgIGRmX2tleSA8LSBzdXBwcmVzc1dhcm5pbmdzKHt0aWJibGUoY29sX2tleXMgPSBuYW1lcyhkZikpICU+JSAgLS0+CjwhLS0gICAgICAgZmlsdGVyKCFncmVwbCgibG9jdXMiLCBjb2xfa2V5cykpICU+JSAgLS0+CjwhLS0gICAgICAgc2VwYXJhdGUoY29sX2tleXMsIGludG8gPSBuZXN0aW5nX3ZhcnMsIHNlcCA9ICItIiwgcmVtb3ZlID0gRikgJT4lIC0tPgo8IS0tICAgICAgIG11dGF0ZV9hdCh2YXJzKGNvbnRhaW5zKCJnZW5vdHlwZXIiKSksIHJlZm9ybWF0X2hsYV9nZW5vdHlwZXIpICU+JSAgLS0+CjwhLS0gICAgICAgYXJyYW5nZV9hdChuZXN0aW5nX3ZhcnMpICU+JSAgLS0+CjwhLS0gICAgICAgbXV0YXRlX2FsbChhcy5jaGFyYWN0ZXIpIC0tPgo8IS0tICAgfSkgLS0+Cgo8IS0tICAgdmxpbmVfdmFyIDwtIHRhaWwobmVzdGluZ192YXJzLDEpIC0tPgo8IS0tICAgdmxpbmVzX3NlcXVlbmNlIDwtIHNlcSgxLG5yb3coZGZfa2V5KSxieSA9IGxlbmd0aCh1bmlxdWUoZGZfa2V5W1t2bGluZV92YXJdXSkpKSAtLT4KPCEtLSAgIGRmIDwtIGRmICU+JSAgLS0+CjwhLS0gICAgIHNlbGVjdChsb2N1cywgZGZfa2V5JGNvbF9rZXlzKSAlPiUgIC0tPgo8IS0tICAgICBmbGV4dGFibGUoKSAlPiUgIC0tPgo8IS0tICAgICBjb2xmb3JtYXRfY2hhcihuYV9zdHIgPSAiLS0tIikgJT4lICAtLT4KPCEtLSAgICAgc2V0X2hlYWRlcl9kZihtYXBwaW5nID0gZGZfa2V5LCBrZXkgPSAiY29sX2tleXMiKSAlPiUgIC0tPgo8IS0tICAgICBtZXJnZV9oKHBhcnQgPSAiaGVhZGVyIikgJT4lICAtLT4KPCEtLSAgICAgdGhlbWVfdmFuaWxsYSgpICU+JSAgLS0+CjwhLS0gICAgIHZsaW5lKGo9dmxpbmVzX3NlcXVlbmNlLCBib3JkZXIgPSBmcF9ib3JkZXJfZGVmYXVsdCgpKSAlPiUgLS0+CjwhLS0gICAgIGZpeF9ib3JkZXJfaXNzdWVzKCkgLS0+CjwhLS0gICByZXR1cm4oZGYpIC0tPgo8IS0tIGBgYCAtLT4KCgoKCgojIFNjcmF0Y2ggd29yawoKPCEtLSBgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTMsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0gLS0+CjwhLS0gc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmICU+JSAgLS0+CjwhLS0gICBmaWx0ZXIoZmllbGQgPT0gImZpZWxkXzIiKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKG5fYWxsZWxlcyA9IGZhY3RvcihuX2FsbGVsZXMsIGxldmVscyA9IDA6MikpICU+JSAgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKHggPSBuX2FsbGVsZXMsIHkgPSBsb2cxMChuX2NlbGxzKSkpKyAtLT4KPCEtLSAgIGdlb21fdmlvbGluKHNjYWxlID0gIndpZHRoIikrIC0tPgo8IS0tICAgZ2VvbV9qaXR0ZXIoc2l6ZSA9IDAuMiwgaGVpZ2h0ID0gMCwgd2lkdGggPTAuMDUsIGFscGhhID0gMC4yKSsgLS0+CjwhLS0gICAjIGdlb21fYm94cGxvdCh3aWR0aD0wLjEpKyAtLT4KPCEtLSAgICMgZ2diZWVzd2FybTo6Z2VvbV9iZWVzd2FybShzaXplID0gMC4xLCBhbHBoYSA9IDAuMSkrIC0tPgo8IS0tICAgY29vcmRfZmxpcCgpKyAtLT4KPCEtLSAgIGZhY2V0X2dyaWQoZ2Vub3R5cGVyIH4gbG9jdXMsIHNjYWxlcyA9ICJmcmVlIikrIC0tPgo8IS0tICAgdGhlbWVfYncoKSAtLT4KPCEtLSBgYGAgLS0+CjwhLS0gIyBDb3ZlcmFnZSBzdGF0cyAtLT4KPCEtLSBgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTMsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0gLS0+CjwhLS0gc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmICU+JSAgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKHggPSBuX2NlbGxzLCB5ID0gY292ZXJhZ2UsIGNvbG9yID0gZ2Vub3R5cGVyKSkgKyAgLS0+CjwhLS0gICBnZW9tX3BvaW50KCkgKyAtLT4KPCEtLSAgIGZhY2V0X3dyYXAoZ2Vub3R5cGVyIH4gbG9jdXMsIHNjYWxlcyA9ICJmcmVlIiwgbnJvdyA9IDMpICsgIC0tPgo8IS0tICAgdGhlbWVfYncoKSArIC0tPgo8IS0tICAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwgLS0+CjwhLS0gICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSsgLS0+CjwhLS0gICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3IsIGZpZy53aWR0aD0xNiwgZmlnLmhlaWdodD0zLCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9IC0tPgo8IS0tIHN1YnNhbXBsZV9jZWxsc19jb21iaW5lZF9kZiAlPiUgIC0tPgo8IS0tICAgc2VsZWN0KC1nZW5vdHlwZXIpICU+JSBkaXN0aW5jdCgpICU+JSAgLS0+CjwhLS0gICBtdXRhdGUoY292X3Blcl9jZWxsID0gY292ZXJhZ2Uvbl9jZWxscykgJT4lICAtLT4KPCEtLSAgIGdncGxvdChhZXMoeCA9IGxvZzEwKG5fY2VsbHMpLCB5ID0gY292X3Blcl9jZWxsKSkgKyAgLS0+CjwhLS0gICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjEpICsgLS0+CjwhLS0gICBzdGF0X3Ntb290aChtZXRob2QgPSAibG0iKSsgLS0+CjwhLS0gICAjIHN0YXRfc21vb3RoKCkrIC0tPgo8IS0tICAgICBmYWNldF93cmFwKCB+IGxvY3VzLCBzY2FsZXMgPSAiZnJlZSIsIG5yb3cgPSAxKSArIC0tPgo8IS0tICAgdGhlbWVfYncoKSArIC0tPgo8IS0tICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkrIC0tPgo8IS0tICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTYsIGZpZy5oZWlnaHQ9Niwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfSAtLT4KPCEtLSBzdWJzYW1wbGVfY2VsbHNfY29tYmluZWRfZGYgJT4lICAtLT4KPCEtLSAgIHNlbGVjdCgtZ2Vub3R5cGVyKSAlPiUgZGlzdGluY3QoKSAlPiUgIC0tPgo8IS0tICAgZmlsdGVyKCFpcy5uYShuX2NlbGxzKSkgJT4lICAtLT4KPCEtLSAgIG11dGF0ZShjb3ZfcGVyX2NlbGwgPSBjb3ZlcmFnZS9uX2NlbGxzKSAlPiUgIC0tPgo8IS0tICAgbXV0YXRlKG5fY2VsbHMgPSBjdXQobl9jZWxscywgc2VxKDAsMTAwMDAsYnk9MjUwMCksIHJpZ2h0ID0gRikpICU+JSAgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKHggPSBuX2NlbGxzLCB5ID0gY292X3Blcl9jZWxsKSkgKyAgLS0+CjwhLS0gICBzdGF0X3N1bW1hcnkoZnVuID0gZnVuY3Rpb24oeCkgbWVhbih4LG5hLnJtPVQpLCBnZW9tID0gImJhciIpICsgLS0+CjwhLS0gICAjIGdlb21fcG9pbnQoY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuMSkgKyAtLT4KPCEtLSAgICMgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIikrIC0tPgo8IS0tICAgIyBzdGF0X3Ntb290aCgpKyAtLT4KPCEtLSAgIGZhY2V0X3dyYXAoIH4gbG9jdXMsIHNjYWxlcyA9ICJmcmVlIiwgbnJvdyA9IDEpICsgLS0+CjwhLS0gICB0aGVtZV9idygpICsgLS0+CjwhLS0gICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSsgLS0+CjwhLS0gICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIGhpc3QoY3V0KDE6MTAwLCBzZXEoMSwxMDAsMTApKSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gc3Vic2FtcGxlX2NlbGxzX2NvbWJpbmVkX2RmICU+JSAgLS0+CjwhLS0gICB1bmdyb3VwKCkgJT4lICAtLT4KPCEtLSAgIGNvdW50KGdlbm90eXBlciwgbG9jdXMsIGZpZWxkKSAtLT4KPCEtLSBgYGAgLS0+CjwhLS0gYGBge3J9IC0tPgo8IS0tIHN1YnNhbXBsZV9yZWFkc19jb21iaW5lZF9kZiAlPiUgIC0tPgo8IS0tICAgdW5ncm91cCgpICU+JSAgLS0+CjwhLS0gICBjb3VudChnZW5vdHlwZXIsIGxvY3VzLCBmaWVsZCkgLS0+CjwhLS0gYGBgIC0tPgo=